/*
 * locks.cc
 *
 *  Created on: Jun 4, 2011
 *      Author: peckb1
 */

#include "locks.h"

Locks::Locks() {
	testNo=-1;
	t1_l1 = new Lock("Test Case 1, Lock");
	t1_c1 = new Condition("Test Case 1, Condition");
	t1_numberOfCustomersReadyToGetIntLines = 0;
	t1_done = new Semaphore("t1_done",0);
	for(int i=0; i< MAXIMUM_OCCUPANCY; i++)
	{
		t1_selectedLines[i]=-1;
	}

    /*
     * Monitor section for the Item-Stockboy/Customer interaction
     */
	int currentAisle = 0;
    for(int i = 0; i < MAX_ITEMS; i++) {
    	//First create the item itself
    	//Random prices between 0.01 and 100
		double price = ((double)(rand() % 100)/100) + (rand() % 101);
		itemsInStore[i] = new Item(i, currentAisle, price, 1);
		//Increment the Aisle
		if((i+1) % MAX_ITEMS_PER_AISLE == 0){
			currentAisle ++;
		}
		//Set the locks and CVs
        char *name = new char[40];
        sprintf(name, "StockBoy/Customer Lock/CV %i\n", i);
        _shelfLock[i] = new Lock(name);
        _itemWaitCV[i] = new Condition(name);
        _stockBoyReStockingItem[i]=NOT_FOUND;
    }
    _customerWaitingForReStockLock = new Lock("Customers waiting restock lock");


    /*
     * Lock for StockBoy-StockRoom interaction
     * Used by stockboys
     */
    _stockRoomLock = new Lock("Stock Room Lock");
    _stockRoomStatusLock = new Lock("Stock Room status lock");
    _stockRoomCV = new Condition("Stock Room CV");
    _stockBoyIdInStockRoom = NOT_FOUND;

    _stockBoyOrderLock = new Lock("StockBoyBoy");

    /*
     * Lock for Customer-StockBoy interaction
     * Used by customer to determine if a stock boy is in certain aisle
     */
    _stockBoysStatusLock = new Lock("StockBoy Status Lock");

    /*
     * Monitor for stock boys going on break and a manager waking them up
     */
    _stockBoyBreakLock = new Lock("StockBoys on Break Lock");
    _stockBoysOnBreakCV = new Condition("StockBoys on Break CV");

    /*
     * Monitor for Clerks going on break and a manager waking them up
     */
    _clerksOnBreakLock = new Lock("Clerks on Break Lock");
    _clerksOnBreakCV = new Condition("Clerks on Break CV");

    /*
     * Monitor for Clerks requesting more clerks to come off break
     */
    _signalManagerClerkHelp = new Lock("Signal Manager Clerk Help Lock");

    /*
     * Monitor for Customer waiting for a clerk coming back from break
     */
    _customerNeedsClerkAssitanceLock = new Lock("Customer needs Clerk Assistance Lock");
    _customerNeedsClerkAssitanceCV = new Condition("Customer Needs Clerk Assistance CV");
    _customerShouldFindTheClerkCV = new Condition("Customer finding clerk");
    /*
     * Monitor for Manager giving money to cash Register
     */
    _registerNeedsMoney = new Lock("Register Needs Money");
    for(int i = 0; i < MAX_CLERKS; i++) {
        char *name = new char[40];
        sprintf(name, "Register Needs Money CV %i\n", i);
        _registerNeedsMoneyCV[i] = new Condition(name);
        //NEW
        _clerkWantsToInteract[i] = -1;
        _managerWantsToInteract[i] = -1;
    }

    /*
     * Monitor for Customer-StockBoy interaction
     * Customers Waiting to ask the question
     */
    for(int i = 0; i < NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS; i++) {
        char *name = new char[40];
        sprintf(name, "StockBoy/Customer Wait Lock/CV %i\n", i);
        _stockBoyIdInAisleToAnswerQuestionMV[i]=NOT_FOUND;
        _customersWaitingInAisleToAskQuestionLock[i] = new Lock(name);
        _customersWaitingInAisleToAskQuestionCV[i] = new Condition(name);
    }

    /*
     * Monitor for Customer-StockBoy interaction
     * Customer handing item# to stock boy
     */
    for(int i = 0; i < MAX_STOCKBOYS; i++) {
        char *name = new char[40];
        sprintf(name, "StockBoy/Customer Item Lock/CV %i\n", i);

        _customerItemQuestionLock[i] = new Lock(name);
        _customerItemQuestionCV[i] = new Condition(name);
    }

    /*
     * Monitor for Customer-StockBoy interaction
     * Stock boy handing Aisle# to customer
     */
    for(int i = 0; i < MAX_STOCKBOYS; i++) {
        char *name = new char[40];
        sprintf(name, "StockBoy/Customer Aisle Lock/CV %i\n", i);

        _stockBoyAisleAnswerLock[i] = new Lock(name);
        _stockBoyAisleAnswerCV[i] = new Condition(name);
    }

    // Used for Customer getting in line and Clerks going on break
    _clerkLinelock = new Lock("Clerk Line Lock");
    for(int i = 0; i < MAX_CLERKS; i++) {
        char *name = new char[40];
        sprintf(name, "ClerkLineCV %i\n", i);
        _clerkLineCV[i] = new Condition(name);
    }

    // Used in communication between customer and clerk
    for(int i = 0; i < MAX_CLERKS; i++) {
        char *name = new char[60];
        sprintf(name, "Customer/Clerk Lock/CV %i\n", i);

        _clerkLock[i] = new Lock(name);
        _clerkCV[i] = new Condition(name);
        _customerLock[i] = new Lock(name);
        _customerCV[i] = new Condition(name);
        _ItemPassingClerkLock[i]= new Lock(name);
        _ItemPassingClerkCV[i]= new Condition(name);

        registerSales[i]=0;
    }

    totalStoreSales = 0;
    /*
     * Three clerk/customer locks for passing money
     */
    for(int i = 0; i < MAX_CLERKS; i++) {
        char *name = new char[60];
        sprintf(name, "Clerk/Customer Money Lock/CV %i\n", i);

        _customerWaitForTotalLock[i] = new Lock(name);
        _customerWaitForTotalCV[i] = new Condition(name);
        _clerkWaitForMoneyLock[i] = new Lock(name);
        _clerkWaitForMoneyCV[i] = new Condition(name);
        _customerWaitForReceiptLock[i] = new Lock(name);
        _customerWaitForReceiptCV[i] = new Condition(name);
        _clerkWaitForCustomerLeavingLock[i] = new Lock(name);
        _clerkWaitForCustomerLeavingCV[i] = new Condition(name);
    }

    // Clerk and Manager talking with Cash Registers
    for(int i = 0; i < MAX_CLERKS; i++) {
        char *name = new char[60];
        sprintf(name, "Register Lock/CV %i\n", i);

        _registerLock[i] = new Lock(name);
        _registerCV[i] = new Condition(name);;
        _toRegisterInteractionLock[i] = new Lock(name);
        _toRegisterInteractionCV[i] = new Condition(name);
        _fromRegisterInteractionLock[i] = new Lock(name);
        _fromRegisterInteractionCV[i] = new Condition(name);
    }

     /*
     * Monitor for knowing what a customer wants to do when they reach a clerk
     * each customer alters when they are sending their first item to a clerk
     */
    _customerActionLock = new Lock("Customer Action Lock");

    // Customer enters or leaves the store
    _occupancyLock = new Lock("Occupancy Lock");
    _storeDoorCV = new Condition("Store Door CV\n");
    //
    //
    for (int i = 0; i <MAX_ITEMS; i++)
    {
    	_itemStockOnShelf[i]=0;
    	_customersWaitingForRestock[i]=0; //Initial values set to zero
    }
    for (int i = 0; i <MAX_CLERKS; i++)
	{
    	_storeNeedsMoreClerks[i] = false;
		_moneyNeededForTill[i]=0;
		_moneyGivenToTill[i]=0;
		_clerkLineLength[i]=0; //Line length for each clerk
		_nextItem[i]=0; // set to -1 for no more items
		_orderTotal[i]=0;
		_ammountPaid[i]=0;
		_receipt[i]=false;
		_customerBeingHelped[i]=0; // used for register to know what customer is being used
		_moneyToTransfer[i]=0;
		_requestingTotal[i]=false;
		_managerEmtpyingTill[i]=-2;
		_peopleWaitingForCashRegister[i]=0;
		_customerWantsToScanItems[i]=true; // true if wanting to scan the item, false if return
		_peopleWaitingForCashRegiterCV[i] = new Condition("CashRegister");
		_peopleWaitingForCashRegiterLock[i] = new Lock("Cash Wait Lock");
	}
    for (int i = 0; i< MAX_STOCKBOYS; i++)
    {
    	_stockBoysStatus[i]=-1;
    	_customerItemQuestionMV[i]=-1;
		_customerID_AskingQuestionMV[i]=-1;
		_stockBoyAisleAnswerMV[i]=-1;
    }
    for (int i = 0; i < NUM_CUSTOMERS_WAIT_LINES_FOR_STOCKBOYS; i++)
    {
    	_customersWaitingInAisleToAskQuestionMV[i]=0;
    }
    _stockBoyIdInStockRoom = NOT_FOUND;
	_stockBoysWaitingForStockRoomCV = 0;
	_stockBoyOnBreakMV = 0;
	_clerksOnBreakMV = 0;
	_customersNeedingAsistanceMV = 0;
	_registersThatNeedMoney = 0;
};
Locks::~Locks() {

};

//Lock* Locks::GetClerkCustomerCheckoutInteractionLock(int lineId) {
//    return _clerkCustomerCheckoutInteractionlocks[lineId];
//};
//Lock* Locks::GetClerkManagerRegisterInteractionLock(int lineId) {
//    return _clerkManagerRegisterInteractionLocks[lineId];
//};
Lock* Locks::GetGlobalLineLock() {
    return _clerkLinelock;
};

//Lock* Locks::GetCustomerStockBoyItemInteractionLock(int itemNumber) {
//    return _customerStockboyItemInteractionLocks[itemNumber];
//};

Condition* Locks::GetClerksOnBreakCV() {
    return _clerksOnBreakCV;
};
Condition* Locks::GetStockBoysOnBreakCV() {
    return _stockBoysOnBreakCV;
};
//Condition* Locks::GetClerkCustomerItemTransferCV(int lineId) {
//    return _clerkCustomerItemTransferCVs[lineId];
//};


//===> Added by peskanda
/*
 * Lock for StockBoy-StockRoom interaction
 * Used by stock boys to make the stock room mutual exclusive
 */
Lock* Locks::GetStockRoomLock()
{
	return _stockRoomLock;
}
/*
 * Lock for Customer-StockBoy interaction
 * Used by customer to determine if a stock boy is in certain aisle
 */
Lock* Locks::GetStockBoysStatusLock()
{
	return _stockBoysStatusLock;
}
void Locks::SetStockBoysStatus(int stockBoyID, int newStatus)
{
	ASSERT (stockBoyID >= 0 && stockBoyID < MAX_STOCKBOYS);
	_stockBoysStatusLock->Acquire();
	_stockBoysStatus[stockBoyID] = newStatus;
	_stockBoysStatusLock->Release();
}
int Locks::GetStockBoysStatus(int stockBoyID)
{
	ASSERT (stockBoyID >= 0 && stockBoyID < MAX_STOCKBOYS);
	return _stockBoysStatus[stockBoyID];
}
/*
 * Monitor for Customer-StockBoy interaction
 * Customers Waiting to ask the question
 */
Lock* Locks::GetCustomersWaitingInAisleToAskQuestionLock(int aisleNumber)
{
	return _customersWaitingInAisleToAskQuestionLock[aisleNumber];
}

int* Locks::GetCustomersWaitingInAisleToAskQuestionMV(int aisleNumber)
{
		//NOTE: Please notice this should return a pointer since we need to modify its content
	return &_customersWaitingInAisleToAskQuestionMV[aisleNumber];
}

Condition* Locks::GetCustomersWaitingInAisleToAskQuestionCV(int AisleNumber)
{
	return _customersWaitingInAisleToAskQuestionCV[AisleNumber];
}
/*
 * Monitor for Customer-StockBoy interaction
 * Customer handing item# to stock boy
 */
Lock* Locks::GetCustomerItemQuestionLock(int stockBoyIndex)
{
	return _customerItemQuestionLock[stockBoyIndex];
}
int* Locks::GetCustomerItemQuestionMV(int stockBoyIndex)
{
	//NOTE: Please notice this should return a pointer since we need to modify its content
	return &_customerItemQuestionMV[stockBoyIndex];
}
Condition* Locks::GetCustomerItemQuestionCV(int stockBoyIndex)
{
	return _customerItemQuestionCV[stockBoyIndex];
}
/*
 * Monitor for Customer-StockBoy interaction
 * Stock boy handing Aisle# to customer
 */
Lock* Locks::GetStockBoyAisleAnswerLock(int stockBoyIndex)
{
	return _stockBoyAisleAnswerLock[stockBoyIndex];
}
int* Locks::GetStockBoyAisleAnswerMV(int stockBoyIndex)
{
	//NOTE: Please notice this should return a pointer since we need to modify its content
	return &_stockBoyAisleAnswerMV[stockBoyIndex];
}
Condition* Locks::GetStockBoyAisleAnswerCV(int stockBoyIndex)
{
	return _stockBoyAisleAnswerCV[stockBoyIndex];
}
//<=== End of the changes by peskanda
//
//Item* Locks::GetSharedClerkCustomerItem(int lineId) {
//    return _sharedClerkCustomerItems[lineId];
//}

